/**
 * LogService.java
 * 版权所有(C) 2013 
 * 创建:cuiran 2013-7-4 下午5:01:44
 */
package com.ghyf.mplay.service;

import java.io.DataOutputStream;
import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;  
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import com.ghyf.mplay.net.common.GData;
import com.ghyf.mplay.net.common.RecvBase;
import com.ghyf.mplay.net.log.RunLogData;
import com.ghyf.mplay.net.log.RunLogQueue;
import com.ghyf.mplay.net.log.thread.HandlerThreadFactory;
import com.ghyf.mplay.util.LogUtil;
import com.ghyf.mplay.util.VeDate;
import com.ghyf.mplay.value.ConstantValue;
  
import android.annotation.SuppressLint;
import android.app.AlarmManager;  
import android.app.PendingIntent;  
import android.app.Service;  
import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.content.IntentFilter;  
import android.os.Environment;  
import android.os.IBinder;  
import android.util.Log;

  
/** 
 * 
 * 运行日志服务，日志默认会存储在SDcar里如果没有SDcard会存储在内存中的安装目录下面。<br>
 * 0.记录播放日志文件 <br>
 * 1.本服务默认在SDcard中每天生成一个日志文件, <br>
 * 2.如果有SDCard的话会将之前内存中的文件拷贝到SDCard中 <br>
 * 3.如果没有SDCard，在安装目录下只保存当前在写日志 <br>
 * 4.SDcard的装载卸载动作会在步骤2,3中切换 <br>
 * 5.SDcard中的日志文件只保存30天 <br>
 * @author cuiran
 * @version 1.0
 */
public class RunLogService extends Service {
	 private static final String TAG = "RunLogService";  
	
	 private String LOG_PATH_SDCARD_DIR;                                         //日志文件在sdcard中的路径  
	 private static String MONITOR_LOG_SIZE_ACTION = "MONITOR_LOG_SIZE";         //日志文件监测action  
	 private static String SWITCH_LOG_FILE_ACTION = "SWITCH_LOG_FILE_ACTION";    //切换日志文件action  
	 private DataOutputStream dos = null;
	 final ExecutorService exec = Executors.newFixedThreadPool(1,new HandlerThreadFactory());
	 
	 @SuppressLint("SimpleDateFormat")
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//日志名称格式  1001_002.Play.20131203.log
	 private LogTaskReceiver logTaskReceiver;   
	/* (non-Javadoc)
	 * @see android.app.Service#onBind(android.content.Intent)
	 */
	@Override
	public IBinder onBind(Intent arg0) {
		
		return null;
	}

	/* (non-Javadoc)
	 * @see android.app.Service#onCreate()
	 */
	@Override
	public void onCreate() {
	
		super.onCreate();
		LogUtil.i(TAG, "PlayLogService onCreate");
		
		init();
		
		register();
		
		deploySwitchLogFileTask();
		
		new LogDealThread().start();
	}
	/**
	 * 
	 *  日志文件处理线程<br>
	 * 1、删除超过存储日期的文件<br>
	 * @author cuiran
	 * @version 1.0.0
	 */
	public class LogDealThread extends Thread{

		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			
			deleteSDcardExpiredLog();
			super.run();
		}
		
		
	}
	
	
	 private void register(){  
		 	IntentFilter logTaskFilter = new IntentFilter();  
	        logTaskFilter.addAction(MONITOR_LOG_SIZE_ACTION);  
	        logTaskFilter.addAction(SWITCH_LOG_FILE_ACTION);  
	        logTaskReceiver = new LogTaskReceiver();  
	        registerReceiver(logTaskReceiver,logTaskFilter);  
	 }
	 
	 	/** 
	     * 部署日志切换任务，每天凌晨切换日志文件 
	     */  
	  private void deploySwitchLogFileTask() {  
	        Intent intent = new Intent(SWITCH_LOG_FILE_ACTION);  
	        PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);  
	        Calendar calendar = Calendar.getInstance();  
	        calendar.add(Calendar.DAY_OF_MONTH, 1);  
	        calendar.set(Calendar.HOUR_OF_DAY, 0);  
	        calendar.set(Calendar.MINUTE, 0);  
	        calendar.set(Calendar.SECOND, 0);  
	  
	        // 部署任务  
	        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);  
	        am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, sender);  
	       
	    }  
	  
	 
	   /** 
	     * 日志任务接收 
	     * 切换日志，监控日志大小 
	     * @author Administrator 
	     * 
	     */  
	    class LogTaskReceiver extends BroadcastReceiver{  
	        public void onReceive(Context context, Intent intent) {  
	            String action = intent.getAction();  
	            if(SWITCH_LOG_FILE_ACTION.equals(action)){  
	            	createLogFile();
	            }else if(MONITOR_LOG_SIZE_ACTION.equals(action)){  
	                
	            }  
	        }  
	    }  
	/* (non-Javadoc)
	 * @see android.app.Service#onStart(android.content.Intent, int)
	 */
	@SuppressWarnings("deprecation")
	@Override
	public void onStart(Intent intent, int startId) {
		
		LogUtil.i(TAG, "PlayLogService onStart");
		
		
		super.onStart(intent, startId);
	}

	/**
	 * 2013-12-2 下午1:44:17
	 * 
	 */
	private void init() {
		
		 LOG_PATH_SDCARD_DIR =  ConstantValue.LOG_DIR;  
		 
		 createLogDir();  
		 
		 createLogFile();
		 
		 exec.submit(new LogWriteThread());
		 
	}  
	
	public   void WriteFixBytes(DataOutputStream dout, byte[] bWrite, int length)
	{
		if(length <= 0)
		{	return;
		}
//		byte[] bNull = new byte[length];			
		try
		{
			if(bWrite.length <= length)
			{
				dout.write(bWrite, 0, bWrite.length);				// write bWrite.length bytes
				StringBuffer sb=new StringBuffer();
				int leftLength=length - bWrite.length;
				for(int i=0;i<leftLength;i++){
					sb.append(" ");
				}
				dout.write(sb.toString().getBytes(), 0, leftLength);		// write remain bytes
			}
			else
			{
				dout.write(bWrite, 0, length);						// write length bytes, ignore others
			}
		}
		catch(IOException e)
		{
			
		}
	}
	public   void WriteFixBytes1(DataOutputStream dout, byte[] bWrite, int length)
	{
		if(length <= 0)
		{	return;
		}
		byte[] bNull = new byte[length];			
		try
		{
			if(bWrite.length <= length)
			{
				dout.write(bWrite, 0, bWrite.length);				// write bWrite.length bytes
				dout.write(bNull, 0, length - bWrite.length);		// write remain bytes
			}
			else
			{
				dout.write(bWrite, 0, length);						// write length bytes, ignore others
			}
		}
		catch(IOException e)
		{
			
		}
	}
	
	  class LogWriteThread extends Thread {

		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			
			RunLogData data=null;
			while(true){
				try{
					data=(RunLogData)RunLogQueue.getLogData();
					if(null!=data){
						WriteFixBytes(dos,data.getLineCode().getBytes(), GData.LINE_CODE_LENGTH);
						WriteFixBytes(dos,data.getStationCode().getBytes(), GData.STATION_CODE_LENGTH);
						WriteFixBytes(dos,data.getDeviceCode().getBytes(), GData.DEVICE_CODE_LENGTH);
			            dos.write(data.getLogTime().getBytes());
			            WriteFixBytes(dos,data.getOperationType().getBytes(RecvBase.charset), GData.OPERATION_TYPE_LENGTH);
			            dos.write(data.getOperationDes().getBytes(RecvBase.charset));
			            dos.write("\n".getBytes());
					}
					
				}catch(Exception e){
					LogUtil.e(TAG, "LogWriteThread-error", e);
				}
				
			}
			
			
		}  
		  
	  }
    /**创建日志文件<br>
	 * 2013-12-2 下午1:52:59
	 * 
	 */
	private void createLogFile() {
		
		 String logFileName =GData.strDeviceID+".Run."+VeDate.getStringTodayShort() + ".log";// 日志文件名称  
		  FileOutputStream fos = null;
		  try {
			  boolean isWrite=true;
			  File file=new File(LOG_PATH_SDCARD_DIR+"/"+logFileName);
			  if(file.exists()&&file.isFile()){
				  isWrite=false;
			  }
			  fos=new FileOutputStream(LOG_PATH_SDCARD_DIR+"/"+logFileName, true);
			  dos=new DataOutputStream(fos);
			  if(isWrite){
				  dos.write(GData.run_file_mark.getBytes());
		          dos.write(GData.version_mark.getBytes());
		          WriteFixBytes(dos, "".getBytes(),  GData.RESERVED_LENGTH);
		          dos.write("\n".getBytes());
			  }
			 
		  }catch(Exception e){
			  LogUtil.e(TAG, "createLogFile error", e);
		  }
		 
		  
	}

	/** 
     * 创建日志目录 
     */  
    private void createLogDir() {  
    	File file =null;
    	boolean mkOk;  
    	if (Environment.getExternalStorageState().equals(  
                Environment.MEDIA_MOUNTED)) {  
            file = new File(LOG_PATH_SDCARD_DIR);  
            if (!file.isDirectory()) {  
                mkOk = file.mkdirs();  
                if (!mkOk) {  
                    LogUtil.i(TAG, "dir is not created succ");  
                    return;  
                }  
            }  
        }  
    }
    
    /** 
     * 去除文件的扩展类型（.log） 
     * @param fileName 
     * @return 
     */  
    private String getFileNameWithoutExtension(String fileName){  
    	try{
    		
    		return fileName.substring((fileName.length()-12), fileName.length()-4);
    	
    	}catch(Exception e){
    		return "";
    	}
    	
    }  
  
    /** 
     * 删除内存下过期的日志 
     */  
    private void deleteSDcardExpiredLog() {  
        File file = new File(LOG_PATH_SDCARD_DIR);  
        if (file.isDirectory()) {  
            File[] allFiles = file.listFiles();  
            for (File logFile : allFiles) {  
                String fileName = logFile.getName();  
                String createDateInfo = getFileNameWithoutExtension(fileName);  
                if (canDeleteSDLog(createDateInfo)) {  
                    logFile.delete();  
                    LogUtil.i(TAG, "delete expired log success,the log path is:"  
                            + logFile.getAbsolutePath());  
                }  
            }  
        }  
    }  
      
    /** 
     * 判断sdcard上的日志文件是否可以删除 
     * @param createDateStr 
     * @return 
     */  
    public boolean canDeleteSDLog(String createDateStr) {  
        boolean canDel = false;  
        Calendar calendar = Calendar.getInstance();  
        calendar.add(Calendar.DAY_OF_MONTH, -1 *GData.sdcard_log_file_save_days);//删除7天之前日志  
        Date expiredDate = calendar.getTime();  
        try {  
            Date createDate = sdf.parse(createDateStr);  
            canDel = createDate.before(expiredDate);  
        } catch (ParseException e) {  
            Log.e(TAG, e.getMessage(), e);  
            canDel = false;  
        }  
        return canDel;  
    }  
}  
